/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ve.usb.cep.db.models;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;

import ve.usb.cep.db.SelectObject;
import ve.usb.cep.db.SelectException;
import ve.usb.cep.db.Session;
import ve.usb.cep.db.domainObjects.Usuario;
import ve.usb.cep.db.modelExceptions.UsuarioException;
import ve.usb.cep.util.Hash;
import ve.usb.cep.util.sqlWhere;

/**
 *
 * @author Andras
 */
public class UsuarioModel{
    Connection conn;
    PreparedStatement rowCountStatement;

    public Usuario set(Usuario usuario)
        throws UsuarioException
    {

        if (0 == usuario.getCodigo()){
            usuario.setClave(Hash.calcPsw(usuario.getClave()));
            add(usuario);
        }else{
            if ("******".equals(usuario.getClave())){
                ResultSet rs;
                try {
                    conn = Session.connection();
                    PreparedStatement pstmt = conn.prepareStatement("select clave from usuario where codigo=?");
                    pstmt.setInt(1,usuario.getCodigo());
                    rs = pstmt.executeQuery();
                    rs.next();
                    //Usuario uOld = getByCorreo(usuario.getCorreo());
                    //usuario.setClave(uOld.getClave());
                    usuario.setClave(rs.getString(1));
                } catch(java.sql.SQLException e){
                    e.printStackTrace();
                    throw new UsuarioException(e.getMessage());
                }
            }else{
                usuario.setClave(Hash.calcPsw(usuario.getClave()));
            }
            update(usuario);
        }

        return usuario;
    }

    public Usuario add(Usuario usuario)
        throws UsuarioException
    {

        conn = Session.connection();

        try{
            PreparedStatement pstmt = conn.prepareStatement("INSERT INTO usuario " +
                "(nombre, apellido, clave, cedula, rol, telefono, correo, pregunta, respuesta)" +
                " VALUES (?, ?, ?, ?, CAST(? AS rol), ?, ?, ?, ?)");

            pstmt.setString(1, usuario.getNombre());
            pstmt.setString(2, usuario.getApellido());
            pstmt.setString(3, usuario.getClave());
            pstmt.setInt(4, usuario.getCedula());
            pstmt.setString(5, usuario.getRol().toString());
            pstmt.setString(6, usuario.getTelefono());
            pstmt.setString(7, usuario.getCorreo());
            pstmt.setString(8, usuario.getPregunta());
            pstmt.setString(9, usuario.getRespuesta());
            pstmt.executeUpdate();
        }catch(java.sql.SQLException e){
            e.printStackTrace();
            throw new UsuarioException(e.getMessage());
        }
        return usuario;
    }

    public Usuario update(Usuario usuario)
        throws UsuarioException
    {

        conn = Session.connection();

        try{
            PreparedStatement pstmt = conn.prepareStatement("UPDATE usuario " +
              "SET nombre=?, apellido=?, clave=?, cedula=?, rol=CAST(? AS rol), telefono=?, correo=?, pregunta=?, respuesta=?" +
              " WHERE codigo=?");

            pstmt.setString(1, usuario.getNombre());
            pstmt.setString(2, usuario.getApellido());
            pstmt.setString(3, usuario.getClave());
            pstmt.setInt(4, usuario.getCedula());
            pstmt.setString(5, usuario.getRol().toString());
            pstmt.setString(6, usuario.getTelefono());
            pstmt.setString(7, usuario.getCorreo());
            pstmt.setString(8, usuario.getPregunta());
            pstmt.setString(9, usuario.getRespuesta());
            pstmt.setInt(10, usuario.getCodigo());
            pstmt.executeUpdate();
        }catch(java.sql.SQLException e){
            e.printStackTrace();
            throw new UsuarioException(e.getMessage());
        }
        return usuario;
    }

    public void delete(int codigo)
        throws UsuarioException
    {
        
        conn = Session.connection();
        try{
            PreparedStatement p = conn.prepareStatement("DELETE FROM usuario WHERE codigo=?");
            p.setInt(1, codigo);
            p.executeUpdate();
        }catch(SQLException e){
            e.printStackTrace();
            throw new UsuarioException(e.getMessage());
        }
    }

    public Usuario getUniqueCorreo(String correo, int codigo)
        throws UsuarioException
    {
        Usuario u = getByCorreo(correo);
        if (null == u){
            return null;
        }
        if (u.getCodigo() == codigo){
            return null;
        }
        return u;
    }
    public Usuario getByCorreo(String correo)
       throws UsuarioException
    {
        return getByField("correo", correo);
    }

    public Usuario getUniqueCedula(int cedula, int codigo)
        throws UsuarioException
    {
        Usuario u = getByCedula(cedula);
        if (null == u){
            return null;
        }
        if (u.getCodigo() == codigo){
            return null;
        }
        return u;
    }
    public Usuario getByCedula(int cedula)
       throws UsuarioException
    {
        return getByField("cedula", Integer.toString(cedula));
    }
    protected Usuario getByField(String field, String value)
       throws UsuarioException
    {
        sqlWhere w = new sqlWhere();
        sqlWhere.rule[] c = new sqlWhere.rule[1];
        c[0] = w.new rule();
        c[0].setField(field);
        c[0].setOp("eq");
        c[0].setData(value);
        w.setGroupOp(" AND ");
        w.setRules(c);
        
        ArrayList<Usuario> u = getCustom(new SelectObject((short) 1, (short) 1, "", "", w));
        if (0 == u.size()){
            return null;
        }else{
            return u.get(0);
        }
    }
    public ArrayList<Usuario> getCustom(SelectObject s) 
            throws UsuarioException {

        conn = Session.connection();
        s.setConnection(conn);
        s.setFields(Usuario.getFields());
        s.setTypes(Usuario.getTypes());
        s.setTable("usuario");

        String[] uf = Usuario.getFields(), ut = Usuario.getTypes(),
                 fields = new String[uf.length + 1],
                 types = new String[fields.length];
        int i = 0;
        for (String f : uf){
            fields[i ++] = f;
        }
        fields[i ++] = "(nombre||' '||apellido)";
        i = 0;
        for (String t : ut){
            types[i ++] = t;
        }
        types[i ++] = "String";
        s.setFields(fields);
        s.setTypes(types);

        PreparedStatement p;
        try{
            p = s.getSearchQuery();
            rowCountStatement = s.getCountQuery();
        }catch(SelectException e){
            e.printStackTrace();
            throw new UsuarioException(e.getMessage());
        }

        ArrayList<Usuario> arr = new ArrayList<Usuario>();
        try{
            ResultSet rs = p.executeQuery();
            while (rs.next()){
                arr.add(new Usuario(
                    rs.getInt("codigo"),
                    rs.getString("nombre"),
                    rs.getString("apellido"),
                    rs.getString("clave"),
                    rs.getInt("cedula"),
                    rs.getString("rol"),
                    rs.getString("telefono"),
                    rs.getString("correo"),
                    rs.getString("pregunta"),
                    rs.getString("respuesta")
                ));
            }
        }catch(SQLException e){
            e.printStackTrace();
            throw new UsuarioException(e.getMessage());
        }

        return arr;
    }
 
    public int getRowCount()
        throws UsuarioException
    {
        try{
            ResultSet rs = rowCountStatement.executeQuery();
            rs.next();
            return rs.getInt(1);
        }catch(SQLException e){
            e.printStackTrace();
            throw new UsuarioException(e.getMessage());
        }
    }
}